package com.fisherman.config;

import com.fisherman.bean.Car;
import com.fisherman.bean.Color;
import com.fisherman.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @User: fisherman
 * @Date: 2020/5/22 9:03
 *
 * 自动装配
 *      Spring利用依赖注入（DI），完成对IOC容器中各个组件的依赖关系赋值
 *
 *     1.@Autowired  自动注入
 *          1.默认优先按照类型去容器中找对应的组件 applicationContext.getBean(BookDao.class);//找到就赋值
 *          2.如果找到多个相同类型的组件，再将属性名称作为组件的id去容器中查找
 *                          applicationContext.getBean(“bookDao”)
 *          3.@Qualifier("bookDao"),使用@Qualifier指定需要装配的组件id，而不是属性名
 *          4.自动装配默认一定将属性赋值好，没有就会报错，
 *              可以使用@Autowired(required=false);
 *          5.@Primary,让spring进行自动装配的时候，默认使用首选的bean
 *                  也可以继续使用@Qualifier指定需要的bean的名字
 *        BookService{
 *              @Autowired
 *              BookDao bookDao;
 *          }
 *      2.spring还支持使用@Resource(JSR250)和@Inject（JSR330）【java规范注解】
 *              @Resource:可以和@Autowired一样实现自动装配功能，默认是按照组件名称进行装配的
 *              没有能支持@Primary功能没有支持@Autowired(reqiured=false)
 *              @Inject:需要导入javax.inject的包，和Autowired的功能一样，没有reqiured=false功能
 *
 *              @Autowired是Spring定义的； @Resource和@Inject都市java规范
 *
 *        AutowiredAnnotationBeanPostProcessor:解析完成自动按照功能
 *       3.@Autowired:构造器，参数，方法，属性；都是从容器中获取当前组件的值
 *              1.标注在方法的位置  @Bean+方法参数，参数从容器中获取，默认不写@Autowired效果是一样的都能自动装配
 *              2.标书在构造器  如果组件只有一个有参构造器，这个参数构造器的@Autowired可以省略，参数位置的组件还可以自动从容器中获取
 *              3.放在参数位置
 *
 *        4.自定义组价想要使用spring容器底层的一些组件，（ApplicationContexe，BeanFactory，xxx）
 *        自定义实现xxxAware，在创建对象的时候，会调用接口规定的方法注入相关组价，
 *        把spring底层的组件注入到自定义的bean中，
 *        xxxAware;功能使用xxxProcessor
 *              ApplicationContextAware ==> ApplicationContextAwareProcessor
 *
 *         *Profile
 *  *      Spring为我们提供的可以根据当前环境，动态的激活和切换一系列组件功能
 *  *
 *  *  开发环境，测试环境，生产环境
 *  * 数据（/a）(/b)(/b)
 *  *
 *  * @Profile:指定组件在哪个环境的情况下才能被注册容器中，不指定，任何环境下都能注册这个组件
 *  *      1.加了环境表示。只有这个环境被激活的时候才能注册到容器中，默认是default环境
 *  *      2.写在配置类上，只有指定的环境的时候，整个配置类里面所有的配置才能生效
 *  *      3.没有标注环境表示的bean在任何环境下都是加载的bean
 *
 */
@Configuration  //告诉spring这个是配置类
@ComponentScan({"com.fisherman.service","com.fisherman.dao","com.fisherman.controller","com.fisherman.bean"})
public class MainConifgOfAutowired {

    @Primary
    @Bean("bookDao2")
    public BookDao bookDao(){
        BookDao bookDao = new BookDao();
        bookDao.setLable("23");
        return bookDao;
    }

    /**
     * @Bean标注的方法创建对象的时候，方法参数的值从容器中获取
     * @param car
     * @return
     */
    @Bean
    public Color color(Car car){
        Color color = new Color();
        color.setCar(car);
        return color;
    }
}
